﻿//Copyright (c) Microsoft Corporation. All rights reserved.

using Microsoft.Ted.Wacel.TestConsole.PerformanceTests;
using Microsoft.Ted.Wacel.TestConsole.Properties;
using System;
using System.Diagnostics;

namespace Microsoft.Ted.Wacel.TestConsole
{
    class Program
    {
        static int mTestCount = 0;
        static int mSucceededCount = 0;

        static void Main(string[] args)
        {
            ConsoleColor oldColor = Console.ForegroundColor;
            
            #region Unit tests
            //Redis Data Structures
            RunTestClass(typeof(RedisDictionaryTester));
            RunTestClass(typeof(RedisArrayTester));
            RunTestClass(typeof(RedisCircularBufferTester));
            RunTestClass(typeof(RedisCompressedCircularBufferTester));
            RunTestClass(typeof(RedisCubeTester));
            RunTestClass(typeof(RedisQueueTester));

            //Windows Azure Cache Data Structures
            RunTestClass(typeof(CachedArrayTester));
            RunTestClass(typeof(CachedCircularBufferTester));
            RunTestClass(typeof(CachedCompressedCircularBufferTester));
            RunTestClass(typeof(CachedCubeTester));
            RunTestClass(typeof(CachedQueueTester));

            //Table Storage Data Structures
            RunTestClass(typeof(TableStorageArrayTester));
            RunTestClass(typeof(TableStorageCircularBufferTester));
            RunTestClass(typeof(TableStorageCompressedCircularBufferTester));
            RunTestClass(typeof(TableStorageCubeTester));
            RunTestClass(typeof(TableTester));
            RunTestClass(typeof(TableStorageQueueTester));
            
            //Other Data Structures
            RunTestClass(typeof(QueueTester));
            RunTestClass(typeof(DimensionTester));
            RunTestClass(typeof(SyncRootTester));
            RunTestClass(typeof(CloudTableStorageTester));
            
            RunTestClass(typeof(ArrayTester));
            RunTestClass(typeof(CubeTester));

            #endregion

            #region Unit test summary
            Console.ForegroundColor =  ConsoleColor.White;

            Console.WriteLine("========================================");
            Console.WriteLine(" Test Summary");
            Console.WriteLine("----------------------------------------");
            Console.WriteLine(" Total Tests:  " + mTestCount);
            Console.WriteLine(" Passed:       " + mSucceededCount);
            
            double passRate = mSucceededCount * 1.0 / mTestCount;
            if (passRate == 1)
                Console.ForegroundColor = ConsoleColor.Green;
            else
                Console.ForegroundColor = ConsoleColor.Red;

            Console.WriteLine(" Passing Rate: " + passRate.ToString("P"));
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("========================================");
            Console.WriteLine();

            Console.ForegroundColor = oldColor;
            #endregion

            Console.WriteLine("Done! Press [P/Enter] to run performance tests, or press [Enter] to quit.");
            var input = Console.ReadLine();

            if (string.Compare(input, "p", true) == 0)
                RunPerfTests(CloudTableStoragePerfTester.InsertOrReplace,
                    CloudTableStoragePerfTester.InsertOrReplaceWithBatch,
                    QueuePerfTester.SendReceive200_1KStringsUsingQueue,
                    CachedCubePerfTester.Rollup,
                    CompressedCircularPerfTest.Add,
                    CompressedCircularPerfTest.AddWithLargeBatch,
                    CompressedCircularPerfTest.GPSSimulation,
                    CircularBufferPerfTest.Add);

            Console.ForegroundColor = oldColor;
            Console.WriteLine("Done! Press [Enter] to quit.");
            Console.ReadLine();
        }
        static void RunPerfTests(params Func<Stopwatch, int>[] actions)
        {
            Stopwatch watch = new Stopwatch();
            foreach(var action in actions)
            {
                Console.WriteLine(">>>>> PERFORMANCE TEST: " + action.Method.DeclaringType.Name + "." + action.Method.Name);
                watch.Reset();
                int count = action.Invoke(watch);
                Console.WriteLine("   # of Transactions:   " + count);
                if (count > 0)
                {
                    Console.WriteLine("   Avg Processing Time: " + watch.ElapsedMilliseconds / count + "(ms)");
                    Console.WriteLine("   Throughput:          " + (1000.0 * count / watch.ElapsedMilliseconds).ToString("#.#")  + "(t/s)");
                }
            }
        }
        static void RunTestClass(Type testType)
        {
            var methods = testType.GetMethods(System.Reflection.BindingFlags.Static
                                            | System.Reflection.BindingFlags.Public);

            ConsoleColor oldColor = Console.ForegroundColor;
            foreach (var method in methods)
            {
                VisualTester.AssertCounter = 0;
                VisualTester.SuccessCounter = 0;
                Console.WriteLine(">>>>> Testing " + testType.Name + "." + method.Name + "()");
                try
                {
                    method.Invoke(null, null);
                }
                catch (Exception exp)
                {
                    VisualTester.AssertCounter++;
                    Console.ForegroundColor = ConsoleColor.Red;
                    if (exp.InnerException != null)
                        Console.WriteLine(exp.InnerException.Message);
                    else
                        Console.WriteLine(exp.Message);
                    Console.ForegroundColor = oldColor;
                }
                mTestCount += VisualTester.AssertCounter;
                mSucceededCount += VisualTester.SuccessCounter;
                Console.WriteLine();
            }
        }
    }
}
